package com.wwj.server.control;

import com.wwj.core.server.entity.ControlServer;
import com.wwj.core.server.entity.ControlServerConnect;
import com.wwj.core.server.service.IControlServerConnectService;
import com.wwj.core.server.service.IControlServerService;
import com.wwj.core.wawa.entity.WaWaMachine;
import com.wwj.core.wawa.service.IWaWaMachineService;
import com.wwj.server.control.codc.MessageDecoder;
import com.wwj.server.control.codc.MessageEncoder;
import com.wwj.utils.IpUtil;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;

@Component
public class Server {

    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Resource
    private IControlServerService controlServerService;

    @Resource
    private IControlServerConnectService controlServerConnectService;

    @Resource
    private IWaWaMachineService waWaMachineService;

    private ControlServer controlServer;

    /**
     * 启动
     */
    public void start(String serverName, int port) {

        // 服务类
        ServerBootstrap b = new ServerBootstrap();

        // 创建boss和worker
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            controlServer = controlServerService.findByServerName(serverName);
            if (null == controlServer) {
                controlServer = new ControlServer(serverName, IpUtil.getHostIp(), port);
                controlServerService.createNewServer(controlServer);
            } else {
                controlServer.setIp(IpUtil.getHostIp());
                controlServer.setPort(port);
                controlServer.setIsOnline(ControlServer.ONLINE);
                controlServerService.updateServer(controlServer);
            }

            // 设置循环线程组事例
            b.group(bossGroup, workerGroup);

            // 设置channel工厂
            b.channel(NioServerSocketChannel.class);

            // 设置管道
            b.childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                    ch.pipeline().addLast(new MessageDecoder());
                    ch.pipeline().addLast(new MessageEncoder());
                    ch.pipeline().addLast(new ServerHandler(controlServer));
                }
            });

            b.option(ChannelOption.SO_BACKLOG, 2048)// 链接缓冲池队列大小
                    .childOption(ChannelOption.SO_KEEPALIVE, true);// 启用心跳保活机制
            // 绑定端口
            b.bind(port).sync();


            logger.info("ControlServer服务端已启动,监听端口：{}", port);

            //关闭服务器后调用
            //更改服务器连接情况
            final ControlServer server = controlServer;
            Runtime.getRuntime().addShutdownHook(new Thread() {
                @Override
                public void run() {
                    try {
                        List<WaWaMachine> machines = waWaMachineService.findAll();
                        for (WaWaMachine machine : machines) {
                            machine.setIsOnline(WaWaMachine.OFFLINE);
                            waWaMachineService.updateMachine(machine);
                        }
                    } catch (Exception e) {
                        logger.error("ControlServer停服,关闭娃娃机连接：", e);
                    }
                }
            });
            //更改娃娃机连接情况
            Runtime.getRuntime().addShutdownHook(new Thread() {
                @Override
                public void run() {
                    try {
                        List<ControlServerConnect> connects = controlServerConnectService.findConnects(server.getId());
                        for (ControlServerConnect connect : connects) {
                            connect.setConnected(ControlServerConnect.NOT_CONNECTED);
                            controlServerConnectService.updateConnect(connect);
                        }
                    } catch (Exception e) {
                        logger.error("ControlServer停服,关闭连接：", e);
                    }
                }
            });
            //更改服务器在线状态
            Runtime.getRuntime().addShutdownHook(new Thread() {
                @Override
                public void run() {
                    try {
                        server.setIsOnline(ControlServer.OFFLINE);
                        controlServerService.updateServer(server);
                    } catch (Exception e) {
                        logger.error("ControlServer停服,更改服务器在线状态：", e);
                    }
                }
            });

        } catch (Exception e) {
            logger.error("ControlServer服务端启动异常：", e);
        }
    }
}
